//SPDX-FileCopyrightText: Copyright 2025-2025 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

import React, { useEffect, useState } from "react";
import { observer } from 'mobx-react';
import { Button, Descriptions, message, Modal, Popover, Space, Switch, Table, Tabs, Tag } from "antd";
import { useSeaOtterStores } from "./store";
import type { WatchInfo } from "@/api/seaotter/watch";
import { list as list_watch, get as get_watch, reset_secret, remove as remove_watch, enable as enable_watch, disable as disable_watch } from "@/api/seaotter/watch";
import { get_session } from "@/api/user";
import { request } from "@/utils/request";
import { gen_access_token } from "@/api/project_server";
import type { ColumnsType } from 'antd/lib/table';
import { CopyOutlined, MoreOutlined } from "@ant-design/icons";
import { writeText } from "@tauri-apps/api/clipboard";
import EditWatchModal from "./components/EditWatchModal";
import { open as shell_open } from '@tauri-apps/api/shell';
import ChangeListModal from "./components/ChangeListModal";


const PAGE_SIZE = 20;

interface WatchPanelProps {
    dataVersion: number;
}

const WatchPanel = (props: WatchPanelProps) => {
    const appStore = useSeaOtterStores();

    const [watchInfoList, setWatchInfoList] = useState<WatchInfo[]>([]);
    const [totalCount, setTotalCount] = useState(0);
    const [curPage, setCurPage] = useState(0);
    const [showUseWatchInfo, setShowUseWatchInfo] = useState<WatchInfo | null>(null);
    const [updateWatchInfo, setUpdateWatchInfo] = useState<WatchInfo | null>(null);
    const [resetSecretWatchInfo, setResetSecretWatchInfo] = useState<WatchInfo | null>(null);
    const [removeWatchInfo, setRemoveWatchInfo] = useState<WatchInfo | null>(null);

    const [showChangeWatchId, setShowChangeWatchId] = useState("");

    const loadWatchInfoList = async () => {
        if (appStore.remoteServer == null || appStore.remoteServer.basic_info.addr_list.length == 0) {
            return;
        }
        const sessionId = await get_session();
        const accessRes = await request(gen_access_token({
            session_id: sessionId,
            project_id: appStore.projectId,
            server_id: appStore.remoteServer.server_id,
        }));

        const listRes = await request(list_watch(appStore.remoteServer.basic_info.addr_list[0], {
            access_token: accessRes.token,
            remote_id: appStore.remoteServer.server_id,
            offset: PAGE_SIZE * curPage,
            limit: PAGE_SIZE,
        }));
        setWatchInfoList(listRes.info_list);
        setTotalCount(listRes.total_count);
    };

    const onUpdateWatch = async (watchId: string) => {
        const tmpList = watchInfoList.slice();
        const index = tmpList.findIndex(item => item.watch_id == watchId);
        if (index == -1) {
            return;
        }

        if (appStore.remoteServer == null || appStore.remoteServer.basic_info.addr_list.length == 0) {
            return;
        }
        const sessionId = await get_session();
        const accessRes = await request(gen_access_token({
            session_id: sessionId,
            project_id: appStore.projectId,
            server_id: appStore.remoteServer.server_id,
        }));

        const getRes = await request(get_watch(appStore.remoteServer.basic_info.addr_list[0], {
            access_token: accessRes.token,
            remote_id: appStore.remoteServer.server_id,
            watch_id: watchId,
        }));
        tmpList[index] = getRes.info;
        setWatchInfoList(tmpList);
    };

    const resetSecret = async () => {
        if (resetSecretWatchInfo == null) {
            return;
        }

        if (appStore.remoteServer == null || appStore.remoteServer.basic_info.addr_list.length == 0) {
            return;
        }
        const sessionId = await get_session();
        const accessRes = await request(gen_access_token({
            session_id: sessionId,
            project_id: appStore.projectId,
            server_id: appStore.remoteServer.server_id,
        }));

        await request(reset_secret(appStore.remoteServer.basic_info.addr_list[0], {
            access_token: accessRes.token,
            remote_id: appStore.remoteServer.server_id,
            watch_id: resetSecretWatchInfo.watch_id,
        }));

        await onUpdateWatch(resetSecretWatchInfo.watch_id);
        message.info("重置成功");
        setResetSecretWatchInfo(null);
    };

    const removeWatch = async () => {
        if (removeWatchInfo == null) {
            return;
        }

        if (appStore.remoteServer == null || appStore.remoteServer.basic_info.addr_list.length == 0) {
            return;
        }
        const sessionId = await get_session();
        const accessRes = await request(gen_access_token({
            session_id: sessionId,
            project_id: appStore.projectId,
            server_id: appStore.remoteServer.server_id,
        }));

        await request(remove_watch(appStore.remoteServer.basic_info.addr_list[0], {
            access_token: accessRes.token,
            remote_id: appStore.remoteServer.server_id,
            watch_id: removeWatchInfo.watch_id,
        }));
        await loadWatchInfoList();
        message.info("删除成功");
        setRemoveWatchInfo(null);
    };

    const enableWatch = async (watchId: string) => {
        if (appStore.remoteServer == null || appStore.remoteServer.basic_info.addr_list.length == 0) {
            return;
        }
        const sessionId = await get_session();
        const accessRes = await request(gen_access_token({
            session_id: sessionId,
            project_id: appStore.projectId,
            server_id: appStore.remoteServer.server_id,
        }));

        await request(enable_watch(appStore.remoteServer.basic_info.addr_list[0], {
            access_token: accessRes.token,
            remote_id: appStore.remoteServer.server_id,
            watch_id: watchId,
        }));
        await onUpdateWatch(watchId);
        message.info("打开推送通知");
    };

    const disableWatch = async (watchId: string) => {
        if (appStore.remoteServer == null || appStore.remoteServer.basic_info.addr_list.length == 0) {
            return;
        }
        const sessionId = await get_session();
        const accessRes = await request(gen_access_token({
            session_id: sessionId,
            project_id: appStore.projectId,
            server_id: appStore.remoteServer.server_id,
        }));

        await request(disable_watch(appStore.remoteServer.basic_info.addr_list[0], {
            access_token: accessRes.token,
            remote_id: appStore.remoteServer.server_id,
            watch_id: watchId,
        }));
        await onUpdateWatch(watchId);
        message.info("关闭推送通知");
    };

    const columns: ColumnsType<WatchInfo> = [
        {
            title: "推送通知",
            width: 70,
            render: (_, row: WatchInfo) => (
                <Switch checked={row.enable} onChange={checked => {
                    if (checked) {
                        enableWatch(row.watch_id);
                    } else {
                        disableWatch(row.watch_id);
                    }
                }} />
            ),
        },
        {
            title: "变更记录",
            width: 70,
            render: (_, row: WatchInfo) => (
                <Button type="link" style={{ minWidth: "0px", padding: "0px 0px" }} disabled={row.change_count == 0}
                    onClick={e => {
                        e.stopPropagation();
                        e.preventDefault();
                        setShowChangeWatchId(row.watch_id);
                    }}>{row.change_count}{row.change_count > 0 && " 查看"}</Button>
            ),
        },
        {
            title: "密钥",
            width: 100,
            render: (_, row: WatchInfo) => (
                <Space>
                    ***********
                    <Button type="link" style={{ minWidth: "0px", padding: "0px 0px" }}
                        icon={<CopyOutlined />} title="复制密钥" onClick={e => {
                            e.stopPropagation();
                            e.preventDefault();
                            writeText(row.secret);
                            message.info("复制成功");
                        }} />
                </Space>
            ),
        },
        {
            title: "相关镜像",
            render: (_, row: WatchInfo) => (
                <Space style={{ flexWrap: "wrap" }}>
                    {row.full_image_name_list.map(fullName => (
                        <Tag key={fullName}>{fullName}</Tag>
                    ))}
                </Space>
            ),
        },
        {
            title: "备注",
            dataIndex: "desc",
            width: 100,
            ellipsis: true,
        },
        {
            title: "操作",
            width: 120,
            render: (_, row: WatchInfo) => (
                <Space>
                    <Button type="link" style={{ minWidth: "0px", padding: "0px 0px" }}
                        onClick={e => {
                            e.stopPropagation();
                            e.preventDefault();
                            setShowUseWatchInfo(row);
                        }}>接收通知说明</Button>
                    <Popover placement="bottom" trigger="click" content={
                        <Space direction="vertical">
                            <Button type="link" style={{ minWidth: "0px", padding: "0px 0px" }}
                                onClick={e => {
                                    e.stopPropagation();
                                    e.preventDefault();
                                    setUpdateWatchInfo(row);
                                }}>修改</Button>
                            <Button type="link" danger style={{ minWidth: "0px", padding: "0px 0px" }}
                                onClick={e => {
                                    e.stopPropagation();
                                    e.preventDefault();
                                    setResetSecretWatchInfo(row);
                                }}>重置密钥</Button>
                            <Button type="link" danger style={{ minWidth: "0px", padding: "0px 0px" }}
                                onClick={e => {
                                    e.stopPropagation();
                                    e.preventDefault();
                                    setRemoveWatchInfo(row);
                                }}>删除</Button>
                        </Space>
                    }>
                        <MoreOutlined />
                    </Popover>
                </Space>
            ),
        }
    ];

    useEffect(() => {
        loadWatchInfoList();
    }, [curPage]);

    useEffect(() => {
        if (curPage == 0) {
            loadWatchInfoList();
        } else {
            setCurPage(0);
        }
    }, [props.dataVersion]);

    return (
        <>
            <Table rowKey="watch_id" dataSource={watchInfoList} columns={columns}
                pagination={{ total: totalCount, current: curPage + 1, pageSize: PAGE_SIZE, onChange: page => setCurPage(page - 1), showSizeChanger: false, hideOnSinglePage: true }} />
            {showUseWatchInfo != null && (
                <Modal open mask={false} footer={null} width={600}
                    bodyStyle={{ padding: "8px 10px" }}
                    onCancel={e => {
                        e.stopPropagation();
                        e.preventDefault();
                        setShowUseWatchInfo(null);
                    }}>
                    <Tabs defaultActiveKey="addWatch" type="card" items={[
                        {
                            key: "install",
                            label: <span style={{ fontSize: "16px", fontWeight: 600 }}>安装Agent</span>,
                            children: (
                                <div style={{ maxHeight: "calc(100vh - 300px)", overflowY: "scroll" }}>
                                    <ol style={{ listStyleType: "decimal", paddingLeft: "20px" }}>
                                        <li>从<a onClick={e => {
                                            e.stopPropagation();
                                            e.preventDefault();
                                            shell_open("https://gitcode.com/openseaotter/so_agent/releases");
                                        }}>这里</a>下载最新的Agent程序</li>
                                        <li>在Linux下给程序设置执行权限。chmod a+x ./so_agent &nbsp;<a onClick={e => {
                                            e.stopPropagation();
                                            e.preventDefault();
                                            writeText("chmod a+x ./so_agent");
                                            message.info("复制成功");
                                        }}>复制命令</a></li>
                                        <li>在Linux下以root运行./so_agent config init &nbsp;<a onClick={e => {
                                            e.stopPropagation();
                                            e.preventDefault();
                                            writeText("./so_agent config init");
                                            message.info("复制成功");
                                        }}>复制命令</a></li>
                                        <li>在Linux下以root运行./so_agent service install &nbsp;<a onClick={e => {
                                            e.stopPropagation();
                                            e.preventDefault();
                                            writeText("./so_agent service install");
                                            message.info("复制成功");
                                        }}>复制命令</a></li>
                                        <li>在Linux下以root运行./so_agent service start &nbsp;<a onClick={e => {
                                            e.stopPropagation();
                                            e.preventDefault();
                                            writeText("./so_agent service start");
                                            message.info("复制成功");
                                        }}>复制命令</a></li>
                                    </ol>
                                </div>
                            ),
                        },
                        {
                            key: "addWatch",
                            label: <span style={{ fontSize: "16px", fontWeight: 600 }}>增加通知订阅</span>,
                            children: (
                                <div style={{ maxHeight: "calc(100vh - 300px)", overflowY: "scroll" }}>
                                    在Linux下以root命令运行<br />
                                    /usr/sbin/seaotter_agent config addWatch --serverAddr {appStore.remoteServer?.basic_info.addr_list[0] ?? ""} {showUseWatchInfo.watch_id} {showUseWatchInfo.secret} [SCRIPT_FILE]
                                    &nbsp;<a onClick={e => {
                                        e.stopPropagation();
                                        e.preventDefault();
                                        writeText(`/usr/sbin/seaotter_agent config addWatch --serverAddr ${appStore.remoteServer?.basic_info.addr_list[0] ?? ""} ${showUseWatchInfo.watch_id} ${showUseWatchInfo.secret} [SCRIPT_FILE]`);
                                        message.info("复制成功");
                                    }}>复制命令</a>
                                    <Descriptions bordered column={1} labelStyle={{ width: "150px" }}>
                                        <Descriptions.Item label="SCRIPT_FILE">用户处理变更信息的脚本</Descriptions.Item>
                                    </Descriptions>
                                </div>
                            ),
                        },
                        {
                            key: "test",
                            label: <span style={{ fontSize: "16px", fontWeight: 600 }}>测试脚本</span>,
                            children: (
                                <div style={{ maxHeight: "calc(100vh - 300px)", overflowY: "scroll" }}>
                                    <p>为了方便编写脚本，我们提供了生成框架代码和测试功能</p>
                                    <h4 style={{ fontSize: "16px", fontWeight: 600 }}>生成脚本</h4>
                                    <p>你可以运行/usr/sbin/seaotter_agent script gen [DEST_FILE]
                                        &nbsp;<a onClick={e => {
                                            e.stopPropagation();
                                            e.preventDefault();
                                            writeText("/usr/sbin/seaotter_agent script gen [DEST_FILE]");
                                            message.info("复制成功");
                                        }}>复制代码</a></p>
                                    <Descriptions bordered column={1} labelStyle={{ width: "150px" }}>
                                        <Descriptions.Item label="DEST_FILE">生成目标文件。目前只支持.py(python)和.js(nodejs)结尾的文件</Descriptions.Item>
                                    </Descriptions>
                                    <h4 style={{ fontSize: "16px", fontWeight: 600 }}>测试脚本</h4>
                                    <p>你可以运行/usr/sbin/seaotter_agent script test --changeBefore [BEFORE_CHANGE] --changeAfter [AFTER_CHANGE] --unChange [UNCHANGE_NAME] [SCRIPT_FILE]
                                        &nbsp;<a onClick={e => {
                                            e.stopPropagation();
                                            e.preventDefault();
                                            writeText("/usr/sbin/seaotter_agent script test --changeBefore [BEFORE_CHANGE] --changeAfter [AFTER_CHANGE] --unChange [UNCHANGE_NAME] [SCRIPT_FILE]");
                                            message.info("复制成功");
                                        }}>复制代码</a>
                                    </p>
                                    <p>--unChange [UNCHANGE_NAME]可以重复多次来指定多个位变更镜像名称</p>
                                    <Descriptions bordered column={1} labelStyle={{ width: "150px" }}>
                                        <Descriptions.Item label="BEFORE_CHANGE">变更前的镜像。格式为group/image:tag</Descriptions.Item>
                                        <Descriptions.Item label="AFTER_CHANGE">变更后的镜像。格式为group/image:tag</Descriptions.Item>
                                        <Descriptions.Item label="UNCHANGE_NAME">未变更的镜像。格式为group/image:tag</Descriptions.Item>
                                        <Descriptions.Item label="SCRIPT_FILE">要执行的脚本文件</Descriptions.Item>
                                    </Descriptions>
                                </div>
                            ),
                        }
                    ]} />
                </Modal>
            )}
            {updateWatchInfo != null && (
                <EditWatchModal watchInfo={updateWatchInfo} onCancel={() => setUpdateWatchInfo(null)} onOk={() => {
                    onUpdateWatch(updateWatchInfo.watch_id);
                    setUpdateWatchInfo(null);
                }} />
            )}
            {resetSecretWatchInfo != null && (
                <Modal open title="重置密钥" mask={false}
                    okText="重置" okButtonProps={{ danger: true }}
                    onCancel={e => {
                        e.stopPropagation();
                        e.preventDefault();
                        setResetSecretWatchInfo(null);
                    }}
                    onOk={e => {
                        e.stopPropagation();
                        e.preventDefault();
                        resetSecret();
                    }}>
                    <p>是否重置&nbsp;{resetSecretWatchInfo.watch_id}&nbsp;的密钥?</p>
                    <p style={{ color: "red" }}>重置后，需调整相关通知接收程序的配置</p>
                </Modal>
            )}
            {removeWatchInfo != null && (
                <Modal open title="删除配置" mask={false}
                    okText="删除" okButtonProps={{ danger: true }}
                    onCancel={e => {
                        e.stopPropagation();
                        e.preventDefault();
                        setRemoveWatchInfo(null);
                    }}
                    onOk={e => {
                        e.stopPropagation();
                        e.preventDefault();
                        removeWatch();
                    }}>
                    是否删除配置&nbsp;{removeWatchInfo.watch_id}&nbsp;?
                </Modal>
            )}

            {showChangeWatchId != "" && (
                <ChangeListModal watchId={showChangeWatchId} onClose={() => setShowChangeWatchId("")} />
            )}
        </>
    );
};

export default observer(WatchPanel);